﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
using OpenComposite.Base.Structures;
using OpenComposite.Base;
using OpenComposite.Base.Collections;
using OpenComposite.EII.CodeGenerators;
using OpenComposite.Repository.Properties;
using OpenComposite.EII.Repository;
using OpenComposite.Mapper;
using WeifenLuo.WinFormsUI.Docking;

namespace OpenComposite.EII.Forms
{
	public partial class FormUpdateConfigurations : DockContent
	{
		#region Initialization
		/// <summary>
		/// Initializes a new instance of the <see cref="FormUpdateConfigurations"/> class.
		/// </summary>
		public FormUpdateConfigurations()
		{
			InitializeComponent();

			dgvChanges.AutoGenerateColumns = false;

			_items = null;

			_sfGroupHeader = new StringFormat(StringFormat.GenericTypographic);
			_sfGroupHeader.LineAlignment = StringAlignment.Center;
			_sfGroupHeader.Trimming = StringTrimming.EllipsisCharacter;
		}
		#endregion

		#region Protected Members

		#region Methods
		// new
		// override
		/// <summary>
		/// Processes a dialog box key.
		/// </summary>
		/// <param name="keyData">One of the <see cref="T:System.Windows.Forms.Keys"/> values that represents the key to process.</param>
		/// <returns>
		/// true if the keystroke was processed and consumed by the control; otherwise, false to allow further processing.
		/// </returns>
		protected override bool ProcessDialogKey(Keys keyData)
		{
#if DEBUG
			if ( ( ModifierKeys & Keys.Control ) == Keys.Control &&
				 ( keyData & Keys.E ) == Keys.E ) {
				showExample();
				return true;
			}
#endif
			return base.ProcessDialogKey(keyData);
		}
		protected override void OnResize(EventArgs e)
		{
			base.OnResize(e);
			dgvChanges.Refresh();
		}
		#endregion

		#endregion

		#region Private Members

		#region Fields
		private BindingListEx<UpdateConfigurationItem> _items;
		private Dictionary<Repository.Workflow, WFConfig> _workflowConfigs;
		private StringFormat _sfGroupHeader;
		#endregion

		#region Methods

		#region Create Example
		/// <summary>
		/// Shows the example.
		/// </summary>
		[Conditional("DEBUG")]
		private void showExample()
		{
			_items = new BindingListEx<UpdateConfigurationItem>();
			_items.Add(new UpdateConfigurationItem(true, false, false, "Business Process Rules"));
			_items.Add(new UpdateConfigurationItem(false, true, true, "AuthorizationRequirementRule", "Rule Change Old: IF [Role] <> \"Manager\" AND [Role] <> \"Assistant Manager\" ; New: IF [Role] <> \"Manager\"", 0, Resources.png_brule));
			_items.Add(new UpdateConfigurationItem(true, false, false, "Selection Rules"));
			_items.Add(new UpdateConfigurationItem(false, true, true, "FlightCarrierRule", "Rule Change Old: IF [FlightFrom] = \"Los Angeles\" ; New: IF [FlightType] = \"Domestic\" ; New: IF [FlightType] = \"Domestic\"", 0, Resources.png_brule));
			_items.Add(new UpdateConfigurationItem(true, false, false, "Rule Constants"));
			_items.Add(new UpdateConfigurationItem(false, true, true, "HighBudgetScore", "Old Value = 7 ; New Value = 5", 0, Resources.png_constant));

			dgvChanges.DataSource = _items;
		}
		#endregion

		#region Load Configs
		/// <summary>
		/// Loads the processes.
		/// </summary>
		private void loadProcesses()
		{
			this.UseWaitCursor = true;
			this.Refresh();
			try {
				loadProcessesWork();
			} finally {
				this.UseWaitCursor = false;
			}
		}
		/// <summary>
		/// Loads the processes work.
		/// </summary>
		private void loadProcessesWork()
		{
			BindingListEx<Repository.Workflow> workflows = Global.Data.GetRepositoryItems<Repository.Workflow>();
			BindingListEx<RuleConstant> allconstants = new BindingListEx<RuleConstant>();
			BindingListEx<MappingItem> alllogphysmappings = new BindingListEx<MappingItem>();
			BindingListEx<MappingItem> allsubmappings = new BindingListEx<MappingItem>();
			BindingListEx<WebService> allwebservices = new BindingListEx<WebService>();
			BindingListEx<LogicalActivity> alllogActs = new BindingListEx<LogicalActivity>();
			BindingListEx<LogicalWebMethod> alllwms = new BindingListEx<LogicalWebMethod>();
			BindingListEx<Repository.HumanActivity> allhumanActs = new BindingListEx<OpenComposite.EII.Repository.HumanActivity>();
			BindingListEx<BusinessObject> allbobjects = new BindingListEx<BusinessObject>();
			BindingListEx<RepositoryBusinessRule> allrules = new BindingListEx<RepositoryBusinessRule>();

			_workflowConfigs = new Dictionary<OpenComposite.EII.Repository.Workflow, WFConfig>();
			// get workflow items
			foreach ( Repository.Workflow wf in workflows ) {
				BindingListEx<Verb> verbs = new BindingListEx<Verb>();
				BindingListEx<LogicalActivity> logActs = new BindingListEx<LogicalActivity>();
				BindingListEx<RepositoryBusinessRule> rules = new BindingListEx<RepositoryBusinessRule>();
				BindingListEx<Repository.HumanActivity> humanActs = new BindingListEx<OpenComposite.EII.Repository.HumanActivity>();
				BindingListEx<WebService> webservices = new BindingListEx<WebService>();
				BindingListEx<WorkflowEvent> events = new BindingListEx<WorkflowEvent>();
				BindingListEx<WorkflowMethod> methods = new BindingListEx<WorkflowMethod>();
				BindingListEx<WorkflowField> fields = new BindingListEx<WorkflowField>();
				BindingListEx<BusinessObject> bobjects = new BindingListEx<BusinessObject>();
				BindingListEx<LogicalWebMethod> lwms = new BindingListEx<LogicalWebMethod>();
				BindingListEx<Noun> nouns = new BindingListEx<Noun>();
				BindingListEx<RuleConstant> constants = new BindingListEx<RuleConstant>();
				BindingListEx<MappingItem> logphysmappings = new BindingListEx<MappingItem>();
				BindingListEx<MappingItem> submappings = new BindingListEx<MappingItem>();
				if ( wf.ExtendedProperties.ConfigurationLevel == ConfigurationLevel.CompleteCodeGeneration ) {
					continue;
				}
				UsingItems.GetItemsOfWorkflow(wf, ref verbs, ref logActs, ref rules, ref humanActs,
					ref webservices, ref events, ref methods, ref fields, ref bobjects, ref lwms,
					ref nouns, ref constants, ref logphysmappings, ref submappings);
				WFConfig wfConfig = new WFConfig();
				wfConfig.RepositoryItems.AddRange(convertToIRepositoryItemList<Verb>(verbs));
				wfConfig.RepositoryItems.AddRange(convertToIRepositoryItemList<LogicalActivity>(logActs));
				wfConfig.RepositoryItems.AddRange(convertToIRepositoryItemList<RepositoryBusinessRule>(rules));
				wfConfig.RepositoryItems.AddRange(convertToIRepositoryItemList<Repository.HumanActivity>(humanActs));
				wfConfig.RepositoryItems.AddRange(convertToIRepositoryItemList<WebService>(webservices));
				wfConfig.RepositoryItems.AddRange(convertToIRepositoryItemList<WorkflowEvent>(events));
				wfConfig.RepositoryItems.AddRange(convertToIRepositoryItemList<WorkflowMethod>(methods));
				wfConfig.RepositoryItems.AddRange(convertToIRepositoryItemList<WorkflowField>(fields));
				wfConfig.RepositoryItems.AddRange(convertToIRepositoryItemList<BusinessObject>(bobjects));
				wfConfig.RepositoryItems.AddRange(convertToIRepositoryItemList<LogicalWebMethod>(lwms));
				wfConfig.RepositoryItems.AddRange(convertToIRepositoryItemList<Noun>(nouns));
				wfConfig.RepositoryItems.AddRange(convertToIRepositoryItemList<RuleConstant>(constants));
				wfConfig.MappingItems.AddRange(logphysmappings);
				wfConfig.MappingItems.AddRange(submappings);
				_workflowConfigs.Add(wf, wfConfig);

				allbobjects.AddRange(bobjects);
				allconstants.AddRange(constants);
				allhumanActs.AddRange(humanActs);
				alllogActs.AddRange(logActs);
				alllogphysmappings.AddRange(logphysmappings);
				alllwms.AddRange(lwms);
				allrules.AddRange(rules);
				allsubmappings.AddRange(submappings);
				allwebservices.AddRange(webservices);
			}
			// load configurations
			loadConfigs();
			Dictionary<object, string> oldValues =
				getOldValues(_workflowConfigs, allconstants, alllogphysmappings, allsubmappings,
							 allwebservices, alllogActs, alllwms, allhumanActs);
			// sort lists
			workflows.Sort("Name", ListSortDirection.Ascending);
			allbobjects.Sort("Name", ListSortDirection.Ascending);
			allrules.Sort("Name", ListSortDirection.Ascending);
			allconstants.Sort("Name", ListSortDirection.Ascending);
			alllogphysmappings.Sort("Element", ListSortDirection.Ascending);
			allsubmappings.Sort("Element", ListSortDirection.Ascending);
			alllwms.Sort("Name", ListSortDirection.Ascending);
			allhumanActs.Sort("Name", ListSortDirection.Ascending);
			allwebservices.Sort("Name", ListSortDirection.Ascending);
			// fill config list
			if ( _items == null ) {
				_items = new BindingListEx<UpdateConfigurationItem>();
				_items.AllowEdit = true;
			} else {
				_items.Clear();
			}
			addIRepositoryItemsToList(_items, _workflowConfigs.Keys, "Processes / Composites", oldValues);
			addIRepositoryItemsToList(_items, allbobjects, "Business Objects", oldValues);
			addIRepositoryItemsToList(_items, allrules, "Rules", oldValues);
			addIRepositoryItemsToList(_items, allconstants, "Rule Constants", oldValues);
			addMappingItemsToList(_items, allsubmappings, "Subscription Mapping", oldValues);
			addMappingItemsToList(_items, alllogphysmappings, "Logical-Physical Mapping", oldValues);
			addIRepositoryItemsToList(_items, alllwms, "Logical Methods / Binding", oldValues);
			addIRepositoryItemsToList(_items, allhumanActs, "Human Activities", oldValues);
			addIRepositoryItemsToList(_items, allwebservices, "Web Services", oldValues);

			dgvChanges.ScrollBars = ScrollBars.None;
			try {
				dgvChanges.DataSource = _items;
				#region auto collapse unchecked regions
				foreach ( DataGridViewRow row in dgvChanges.Rows ) {
					UpdateConfigurationItem header = row.DataBoundItem as UpdateConfigurationItem;
					bool allUnchecked = true;
					if ( header == null || !header.IsGroupHeader ) continue;
					if ( row.Index + 1 == dgvChanges.Rows.Count ) break;
					for ( int i = row.Index + 1; i < dgvChanges.Rows.Count; i++ ) {
						try {
							UpdateConfigurationItem childItem = dgvChanges.Rows[i].DataBoundItem as UpdateConfigurationItem;
							if ( childItem == null || childItem.IsGroupHeader ) break;
							if ( childItem.DoUpdate ) { allUnchecked = false; break; }
						} catch ( Exception ex ) { Debug.WriteLine(ex); }
					}
					if ( allUnchecked ) ExpandGroup(row.Index, true);
				}
				#endregion
			} finally {
				dgvChanges.ScrollBars = ScrollBars.Both;
			}
		}

		/// <summary>
		/// Converts to IRepositoryItem list.
		/// </summary>
		/// <typeparam name="T">The type of the list.</typeparam>
		/// <param name="listToConvert">The list to convert.</param>
		/// <returns>The converted list.</returns>
		private BindingListEx<IRepositoryItem> convertToIRepositoryItemList<T>(
			BindingListEx<T> listToConvert)
		{
			return listToConvert.ConvertAll<IRepositoryItem>(
				delegate(T item) { return (IRepositoryItem)item; });
		}
		/// <summary>
		/// Adds the repository items to the update configuration list.
		/// </summary>
		/// <param name="updateConfigurationItems">The update configuration items.</param>
		/// <param name="repositoryItems">The repository items.</param>
		/// <param name="headerText">The header text.</param>
		/// <param name="oldValues">The old values.</param>
		private void addIRepositoryItemsToList(BindingListEx<UpdateConfigurationItem> updateConfigurationItems,
			ICollection repositoryItems, string headerText,
			Dictionary<object, string> oldValues)
		{
			updateConfigurationItems.Add(new UpdateConfigurationItem(true, false, false, headerText));
			foreach ( IRepositoryItem item in repositoryItems ) {
				string oldVal = "";
				if ( oldValues.ContainsKey(item) ) oldVal = oldValues[item];
				UpdateConfigurationItem ucitem = new UpdateConfigurationItem(item, oldVal);
				updateConfigurationItems.Add(ucitem);
				if ( item is Repository.Workflow ) {
					foreach ( var wc in _workflowConfigs ) {
						if ( wc.Key == item ) {
							wc.Value.UpdateItem = ucitem;
							break;
						}
					}
				} else if ( item is Repository.LogicalWebMethod && ucitem.DoUpdate ) {
					// set mappings to updated
					foreach ( var mapitem in updateConfigurationItems ) {
						if ( mapitem.Item is MappingItem && mapitem.ElementText.StartsWith(item.Name + " ") &&
							 ( mapitem.ElementText.Contains("Input") || mapitem.ElementText.Contains("Output") ) ) {
							mapitem.Comment = "Changed";
							mapitem.SetDoUpdate(true);
						}
					}
				} else if ( !( item is Repository.Workflow ) && ucitem.DoUpdate ) {
					foreach ( var wc in _workflowConfigs ) {
						if ( !wc.Value.UpdateItem.DoUpdate ) {
							wc.Value.UpdateItem.DoUpdate = wc.Value.RepositoryItems.Contains(item);
						}
					}
				}
			}
		}
		/// <summary>
		/// Adds the mapping items to the update configuration list.
		/// </summary>
		/// <param name="updateConfigurationItems">The update configuration items list.</param>
		/// <param name="mappingItems">The mapping items collection.</param>
		/// <param name="headerText">The header text.</param>
		/// <param name="oldValues">The old values.</param>
		private void addMappingItemsToList(BindingListEx<UpdateConfigurationItem> updateConfigurationItems,
			ICollection mappingItems, string headerText,
			Dictionary<object, string> oldValues)
		{
			updateConfigurationItems.Add(new UpdateConfigurationItem(true, false, false, headerText));
			foreach ( MappingItem item in mappingItems ) {
				string oldVal = "";
				if ( oldValues.ContainsKey(item) ) oldVal = oldValues[item];
				UpdateConfigurationItem ucitem = new UpdateConfigurationItem(item, oldVal);
				updateConfigurationItems.Add(ucitem);
				if ( ucitem.DoUpdate ) {
					foreach ( var wc in _workflowConfigs ) {
						if ( !wc.Value.UpdateItem.DoUpdate ) {
							wc.Value.UpdateItem.DoUpdate = wc.Value.MappingItems.Contains(item);
						}
					}
				}
			}
		}

		/// <summary>
		/// Loads the configurations.
		/// </summary>
		/// <param name="workflows">The workflows.</param>
		/// <returns></returns>
		private void loadConfigs()
		{
			Configuration c;
			foreach ( var wcitem in _workflowConfigs ) {
				Repository.Workflow wf = wcitem.Key;
				WFConfig wfConfig = wcitem.Value;
				// load workflow configs
				foreach ( string path in wf.ExtendedProperties.ConfigurationFileLocations ) {
					try {
						if ( !Directory.Exists(path) ) continue;
						// load app.config / web.config
						string[] configfiles = Directory.GetFiles(path, "*.config");
						if ( configfiles != null && configfiles.Length > 0 ) {
							foreach ( var item in configfiles ) {
								if ( item.EndsWith("PrecompiledApp.config") ) continue;
								try {
									ExeConfigurationFileMap map = new ExeConfigurationFileMap();
									map.ExeConfigFilename = item;
									c = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
								} catch {
									c = null;
								}
								if ( c != null ) wfConfig.XmlConfigs.Add(c);
							}
						}
						// load *.config.dll
						configfiles = Directory.GetFiles(path, "*.config.dll", SearchOption.AllDirectories);
						if ( configfiles != null && configfiles.Length > 0 ) {
							foreach ( var item in configfiles ) {
								wfConfig.AssemblyConfigPaths.Add(item);
							}
						}
						configfiles = Directory.GetFiles(path, wf.Name + ".dll", SearchOption.AllDirectories);
						foreach ( var item in configfiles ) {
							wfConfig.AssemblyConfigPaths.Add(item);
						}
					} catch { }
				}
			}
		}
		/// <summary>
		/// Gets the old values.
		/// </summary>
		/// <param name="configs">The configs.</param>
		/// <param name="ruleconstants">The ruleconstants.</param>
		/// <param name="logphysmappings">The logphysmappings.</param>
		/// <param name="submappings">The submappings.</param>
		/// <param name="webservices">The webservices.</param>
		/// <param name="logmethods">The logical methods.</param>
		/// <param name="humanActs">The human acts.</param>
		/// <returns></returns>
		private Dictionary<object, string> getOldValues(
			Dictionary<OpenComposite.EII.Repository.Workflow, WFConfig> configs,
			BindingListEx<RuleConstant> ruleconstants,
			BindingListEx<MappingItem> logphysmappings,
			BindingListEx<MappingItem> submappings,
			BindingListEx<WebService> webservices,
			BindingListEx<LogicalActivity> logicalActivities,
			BindingListEx<LogicalWebMethod> logmethods,
			BindingListEx<Repository.HumanActivity> humanActs)
		{
			Dictionary<object, string> oldValues = new Dictionary<object, string>();
			foreach ( var config in configs ) {
				#region read xml configs
				foreach ( var xmlConfig in config.Value.XmlConfigs ) {
					#region read wcf endpoint urls
					var sectiongroup = xmlConfig.SectionGroups["system.serviceModel"];
					if ( sectiongroup == null ) continue;
					var section = sectiongroup.Sections["client"] as System.ServiceModel.Configuration.ClientSection;
					if ( section == null ) continue;
					foreach ( System.ServiceModel.Configuration.ChannelEndpointElement endpoint in section.Endpoints ) {
						foreach ( var ws in webservices ) {
							if ( ws.InterfaceFullName == endpoint.Contract ) {
								if ( !oldValues.ContainsKey(ws) ) {
									oldValues.Add(ws, endpoint.Address.ToString());
								} else {
								}
							}
						}
					}
					#endregion
					foreach ( var key in xmlConfig.AppSettings.Settings.AllKeys ) {
						if ( key.StartsWith("CONST_") ) {
							#region read rule constant values
							RuleConstant rc = findByName<RuleConstant>(ruleconstants, key.Replace("CONST_", ""));
							if ( rc != null ) {
								if ( !oldValues.ContainsKey(rc) ) {
									oldValues.Add(rc, xmlConfig.AppSettings.Settings[key].Value);
								} else {
								}
							}
							#endregion
						} else if ( key.StartsWith("xslt") ) {
							#region read mapping values
							MappingItem mi = null;
							if ( key.ToLower().Contains("subscription") ) {
								mi = findMappingItemByXSLTFieldName(submappings, key);
							} else {
								mi = findMappingItemByXSLTFieldName(logphysmappings, key);
							}
							if ( mi != null ) {
								if ( !oldValues.ContainsKey(mi) ) {
									oldValues.Add(mi, xmlConfig.AppSettings.Settings[key].Value);
								} else {
									// TODO: ?add multiple items?
								}
							}
							#endregion
						} else if ( key.ToLower().EndsWith("url") ) {
							#region read urls
							string nm = key.Substring(0, key.Length - 3);
							IRepositoryItem ri = findByName<WebService>(webservices, nm);
							if ( ri == null ) ri = findByName<Repository.HumanActivity>(humanActs, nm);
							if ( ri != null ) {
								if ( !oldValues.ContainsKey(ri) ) {
									oldValues.Add(ri, xmlConfig.AppSettings.Settings[key].Value);
								} else {
								}
							}
							#endregion
						}
					}
				}
				#endregion
				#region read assembly configs
				string tmpPath = Path.Combine(Helpers.TempPath, Path.GetRandomFileName());
				foreach ( var asmConfigs in config.Value.AssemblyConfigPaths ) {
					if ( !Directory.Exists(tmpPath) ) Directory.CreateDirectory(tmpPath);
					foreach ( string fi in Directory.GetFiles(Path.GetDirectoryName(asmConfigs), "*.dll") ) {
						string fn = Path.Combine(tmpPath, Path.GetFileName(fi));
						if ( !File.Exists(fn) ) File.Copy(fi, fn);
					}
					string tmpAsm = Path.Combine(tmpPath, Path.GetFileName(asmConfigs));
					Assembly asm = Assembly.LoadFile(tmpAsm);
					if ( asmConfigs.ToLower().EndsWith("businessobjects.config.dll") ) {
						#region read business objects
						Type[] types = asm.GetTypes();
						if ( types == null ) continue; ;
						foreach ( Type type in types ) {
							RepositoryInformationAttribute attr = Helpers.GetAttribute<RepositoryInformationAttribute>(type, false);

							// No Attribute found
							if ( attr == null ) continue;
							int boId = attr.RepositoryItemID;
							BusinessObject bo = Global.Data.RepositoryService.GetItem<BusinessObject>(boId);
							if ( bo == null ) continue;
							if ( checkBusinessObjectChanges(bo, type) ) {
								if ( !oldValues.ContainsKey(bo) ) {
									oldValues.Add(bo, "Changed");
								} else {
									oldValues[bo] = "Changed";
								}
							} else {
								if ( !oldValues.ContainsKey(bo) ) {
									oldValues.Add(bo, type.Name);
								}
							}
						}
						#endregion
					} else if ( asmConfigs.ToLower().EndsWith("rules.config.dll") ) {
						#region get old values of business rules
						Type typeRules = asm.GetType("OpenComposite.Orchestration.Rules");
						if ( typeRules == null ) continue;
						foreach ( MethodInfo method in typeRules.GetMethods() ) {
							RepositoryInformationAttribute attrib =
								Helpers.GetAttribute<RepositoryInformationAttribute>(method, false);
							if ( attrib != null && attrib.TypeName == Resources.sBRule ) {
								int ruleid = attrib.RepositoryItemID;
								RepositoryBusinessRule brule = Global.Data.RepositoryService.GetItem<RepositoryBusinessRule>(ruleid);
								if ( brule == null ) continue;
								string hash = Helper.GetMD5HashAsHex(brule.RuleCode);
								if ( attrib.Hash != hash ) {
									if ( !oldValues.ContainsKey(brule) ) {
										oldValues.Add(brule, "Changed");
									} else {
										oldValues[brule] = "Changed";
									}
								}
							}
						}
						#endregion
					} else if ( asmConfigs.ToLower().EndsWith("logical.config.dll") ) {
						#region get old values of logical methods
						Type typeSCalls = asm.GetType(
							"OpenComposite.Orchestration." + config.Key.Name + ".ServiceCalls");
						if ( typeSCalls == null ) continue;
						foreach ( MethodInfo method in typeSCalls.GetMethods() ) {
							var attribs =
								Helpers.GetAttributes<RepositoryInformationAttribute>(method, false);
							if ( attribs == null || attribs.Count == 0 ) continue;
							int idLogicalActivity = -1;
							int idWebMethod = -1;
							int idHumanActivity = -1;
							string namePhysical = null;
							foreach ( var attrib in attribs ) {
								if ( attrib.TypeName == Resources.sLogicalActivity ) {
									idLogicalActivity = attrib.RepositoryItemID;
								} else if ( attrib.TypeName == Resources.sWebMethod || attrib.TypeName == "WebMethod" ) {
									idWebMethod = attrib.RepositoryItemID;
									namePhysical = attrib.Name;
								} else if ( attrib.TypeName == Resources.sHumanActivity ) {
									idHumanActivity = attrib.RepositoryItemID;
									namePhysical = attrib.Name;
								}
							}
							if ( idLogicalActivity > 0 && idWebMethod > 0 ) {
								// search logical activity
								LogicalActivity logact = findLogicalActivity(logicalActivities, idLogicalActivity);
								if ( logact == null ) continue;
								if ( logact.HumanActivityID > 0 ) {
									if ( logact.HumanActivityID != idHumanActivity ) {
										if ( oldValues.ContainsKey(logact.LogicalMethod) ) {
											oldValues[logact.LogicalMethod] += ", " + namePhysical;
										} else {
											oldValues.Add(logact.LogicalMethod, namePhysical);
										}
									}
								} else {
									// compare old with new webmethod
									if ( logact.LogicalMethod != null && logact.LogicalMethod.WebMethodID != idWebMethod ) {
										if ( oldValues.ContainsKey(logact.LogicalMethod) ) {
											oldValues[logact.LogicalMethod] += ", " + namePhysical;
										} else {
											oldValues.Add(logact.LogicalMethod, namePhysical);
										}
									}
								}
							}
						}
						#endregion
					}
					asm = null;
				}
				#endregion
			}
			return oldValues;
		}

		private LogicalActivity findLogicalActivity(
			BindingListEx<LogicalActivity> logActivities, int idLogicalActivity)
		{
			return logActivities.Find(lm => lm.ID == idLogicalActivity);
		}

		/// <summary>
		/// Checks the business object for changes.
		/// </summary>
		/// <param name="businessObject">The business object.</param>
		/// <param name="type">The type.</param>
		/// <returns>Returns <c>true</c> when changes are found. Otherwise <c>false</c>.</returns>
		private bool checkBusinessObjectChanges(BusinessObject businessObject, Type type)
		{
			BindingListEx<BusinessObjectField> fields = new BindingListEx<BusinessObjectField>(businessObject.BusinessObjectFields);
			foreach ( PropertyInfo prop in type.GetProperties() ) {
				if ( prop.Name == "ExtensionData" ) continue;
				BusinessObjectField field = findByName(fields, prop.Name);
				if ( field == null ) return true;
				if ( field.BusinessObject != null ) {
					if ( prop.PropertyType.IsNested ) {
						bool check = false;
						if ( field.Name != prop.Name ) return true;
						if ( field.IsList ) {
							PropertyInfo listProp = null;
							try {
								listProp = prop.PropertyType.GetProperty("Item");
							} catch { }
							if ( listProp == null ) continue;
							check = checkBusinessObjectChanges(field.BusinessObject, listProp.PropertyType);
						} else {
							check = checkBusinessObjectChanges(field.BusinessObject, prop.PropertyType);
						}
						if ( check ) return true;
					}
				}
			}
			return false;
		}

		/// <summary>
		/// Finds a repository items in the list by the name.
		/// </summary>
		/// <typeparam name="T">Repository item type.</typeparam>
		/// <param name="list">The list.</param>
		/// <param name="name">The name.</param>
		/// <returns>The repository item with the requested name, or <c>null</c> if no repository item exists with this name.</returns>
		private T findByName<T>(BindingListEx<T> list, string name) where T : IRepositoryItem
		{
			return list.Find(delegate(T item)
			{
				return item.Name.Equals(name);
			});
		}
		/// <summary>
		/// Finds a BusinessObjectField in the list by the name.
		/// </summary>
		/// <param name="list">The list.</param>
		/// <param name="name">The name.</param>
		/// <returns>The repository item with the requested name, or <c>null</c> if no repository item exists with this name.</returns>
		private BusinessObjectField findByName(BindingListEx<BusinessObjectField> list, string name)
		{
			return list.Find(delegate(BusinessObjectField item)
			{
				return item.Name.Equals(name);
			});
		}

		/// <summary>
		/// Finds the mapping item by XSLT field name.
		/// </summary>
		/// <param name="list">The list of MappingItems.</param>
		/// <param name="xsltFieldName">Name of the XSLT field.</param>
		/// <returns></returns>
		private MappingItem findMappingItemByXSLTFieldName(BindingListEx<MappingItem> list,
			string xsltFieldName)
		{
			foreach ( var mi in list ) {
				string currentFieldName = "";
				if ( mi.Property == "Mapping" ) {
					currentFieldName = Deployment.cxsltInputSubscription;
				} else if ( mi.Property == "Input Mapping" ) {
					currentFieldName = Deployment.cxsltInput;
				} else if ( mi.Property == "Output Mapping" ) {
					currentFieldName = Deployment.cxsltOutput;
				}
				currentFieldName += mi.Element;
				if ( xsltFieldName == currentFieldName ) {
					return mi;
				}
			}
			return null;
		}
		#endregion

		#region Expand / Collapse Groups
		private void ExpandGroup(int groupHeaderRow)
		{
			ExpandGroup(groupHeaderRow, false);
		}
		private void ExpandGroup(int groupHeaderRow, bool collapse)
		{
			if ( groupHeaderRow < 0 ) return;
			try {
				using ( new OpenComposite.Base.WaitMouse() ) {
					ScrollBar hs = null, vs = null;
					foreach ( Control c in dgvChanges.Controls ) {
						if ( c is HScrollBar ) {
							hs = (HScrollBar)c;
						} else if ( c is VScrollBar ) {
							vs = (VScrollBar)c;
						}
					}
					int hscroll = ( hs != null ? hs.Value : 0 );
					int vscroll = ( vs != null ? vs.Value : 0 );
					DataGridViewCell first = dgvChanges.FirstDisplayedCell;
					dgvChanges.ScrollBars = ScrollBars.None;
					try {
						UpdateConfigurationItem item = dgvChanges.Rows[groupHeaderRow].DataBoundItem as UpdateConfigurationItem;
						if ( item == null ) return;
						item.IsCollapsed = collapse;
						if ( groupHeaderRow + 1 == dgvChanges.Rows.Count ) return;
						for ( int i = groupHeaderRow + 1; i < dgvChanges.Rows.Count; i++ ) {
							try {
								UpdateConfigurationItem nextItem = dgvChanges.Rows[i].DataBoundItem as UpdateConfigurationItem;
								if ( nextItem == null ) continue;
								if ( nextItem.IsGroupHeader ) break;
								dgvChanges.Rows[i].Visible = !collapse;
							} catch ( Exception ex ) { Debug.WriteLine(ex); }
						}
					} finally {
						dgvChanges.ScrollBars = ScrollBars.Both;
						if ( hs != null && hscroll < hs.Maximum ) hs.Value = hscroll;
						if ( vs != null && vscroll < vs.Maximum ) vs.Value = vscroll;
						dgvChanges.FirstDisplayedCell = first;
					}
				}
			} catch ( Exception ex ) { Debug.WriteLine(ex); }
		}
		#endregion

		#endregion

		#region Event Handlers
		private void FormUpdateConfigurations_Load(object sender, EventArgs e)
		{
		}
		private void dgvChanges_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
		{
			if ( e.RowIndex < 0 ) {
				// default painting for column headers
				e.Handled = false;
				return;
			}
			UpdateConfigurationItem item = dgvChanges.Rows[e.RowIndex].DataBoundItem as UpdateConfigurationItem;
			if ( item != null ) {
				if ( item.IsGroupHeader ) {
					// all paintings in RowPostPaint event handler
					e.Handled = true;
				} else if ( e.ColumnIndex == colSelectUpdate.Index ) {
					e.Handled = !item.ShowCheckBox;
				} else {
					e.Handled = false;
				}
			} else {
				e.Handled = false;
			}
		}
		private void dgvChanges_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
		{
			if ( e.RowIndex < 0 ) return;
			try {
				UpdateConfigurationItem item = dgvChanges.Rows[e.RowIndex].DataBoundItem as UpdateConfigurationItem;
				if ( item != null && item.IsGroupHeader ) {
					Rectangle rowBounds = new Rectangle(
						-this.dgvChanges.HorizontalScrollingOffset + 1,
						e.RowBounds.Top,
						this.dgvChanges.Columns.GetColumnsWidth(DataGridViewElementStates.Visible) + 2,
						e.RowBounds.Height);
					// paint GroupHeader
					// style 1
					Rectangle rect = rowBounds;
					RectangleF oldClip = e.Graphics.ClipBounds;
					Rectangle clip = rect;
					clip.Width -= clip.X;
					clip.X = 1;
					e.Graphics.SetClip(clip);
					e.Graphics.FillRectangle(SystemBrushes.Window, rowBounds);
					using ( Pen p = new Pen(dgvChanges.GridColor) ) {
						e.Graphics.DrawLine(p, rect.Left, rect.Bottom - 1, rect.Right, rect.Bottom - 1);
					}
					rect = rowBounds;
					rect.Inflate(-2, -2);
					rect.Height--;
					using ( System.Drawing.Drawing2D.LinearGradientBrush brush =
						new System.Drawing.Drawing2D.LinearGradientBrush(rowBounds, Color.RoyalBlue, Color.White, System.Drawing.Drawing2D.LinearGradientMode.Horizontal) ) {
						e.Graphics.FillRectangle(brush, rect);
					}
					rect.Inflate(-3, -3);

					// height difference for vertical centering
					int dy = (int)Math.Round((float)( rect.Height - 9 ) / 2);
					if ( item.IsCollapsed )
						e.Graphics.DrawImage(Resources.plus, new Rectangle(rect.X, rect.Y + dy, 9, 9));
					else
						e.Graphics.DrawImage(Resources.minus, new Rectangle(rect.X, rect.Y + dy, 9, 9));

					rect.Offset(12, 0);

					using ( Font f = new Font(dgvChanges.Font, FontStyle.Bold) ) {
						e.Graphics.DrawString(item.ElementText, f, Brushes.WhiteSmoke, rect, _sfGroupHeader);
					}
					e.Graphics.Flush();
					e.Graphics.SetClip(oldClip);

					#region DISABLED style 2
					//e.Graphics.FillRectangle(SystemBrushes.Window, e.RowBounds);
					//Rectangle rectLine = new Rectangle(e.RowBounds.X, e.RowBounds.Bottom - 2, e.RowBounds.Width, 2);
					//using ( System.Drawing.Drawing2D.LinearGradientBrush brush =
					//    new System.Drawing.Drawing2D.LinearGradientBrush(rectLine, Color.DarkBlue, Color.White, System.Drawing.Drawing2D.LinearGradientMode.Horizontal) ) {
					//    e.Graphics.FillRectangle(brush, rectLine);
					//}
					//Rectangle rectText = e.RowBounds;
					//rectText.Inflate(-5, -5);
					//e.Graphics.DrawString(item.ElementText, dgvChanges.Font, SystemBrushes.ControlText, rectText, _sfGroupHeader);
					#endregion
				}
			} catch ( Exception ex ) { Debug.WriteLine(ex); }
		}

		private void dgvChanges_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
		{
			if ( e.RowIndex < 0 ) return;
			UpdateConfigurationItem item = dgvChanges.Rows[e.RowIndex].DataBoundItem as UpdateConfigurationItem;
			if ( item == null ) return;
			if ( item.IsGroupHeader ) ExpandGroup(e.RowIndex, !item.IsCollapsed);
		}

		private void dgvChanges_CellClick(object sender, DataGridViewCellEventArgs e)
		{
			if ( e.RowIndex < 0 ) return;
			UpdateConfigurationItem item = dgvChanges.Rows[e.RowIndex].DataBoundItem as UpdateConfigurationItem;
			if ( item == null ) return;
			Point exact = dgvChanges.PointToClient(DataGridView.MousePosition);
			if ( dgvChanges.PointToClient(DataGridView.MousePosition).X > 14 ) return;
			if ( e.ColumnIndex == 0 && item.IsGroupHeader ) ExpandGroup(e.RowIndex, !item.IsCollapsed);
		}

		private void tsbtnRefresh_Click(object sender, EventArgs e)
		{
			loadProcesses();
		}

		private void FormUpdateConfigurations_Shown(object sender, EventArgs e)
		{
			loadProcesses();
		}
		private void tsbtnUpdateConfigs_Click(object sender, EventArgs e)
		{
			// OLD: updateConfigs();
			dgvChanges.EndEdit();

			Dictionary<Repository.Workflow, WFConfig> wfc = new Dictionary<OpenComposite.EII.Repository.Workflow, WFConfig>();
			foreach ( var item in _workflowConfigs ) {
				if ( item.Value.UpdateItem.DoUpdate ) {
					wfc.Add(item.Key, item.Value);
				}
			}
			if ( wfc.Count == 0 ) {
				MessageBox.Show("No processes or composites selected.", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
				return; // EXIT
			}
			FormUpdateConfigValidateCompile frm = new FormUpdateConfigValidateCompile(
				Global.Data.RepositoryService,
				_items,
				wfc);
			frm.ShowDialog();

			this.loadProcesses();
		}

		#endregion

		#endregion
	}

	#region Internal Class: UpdateConfigurationItem
	internal class UpdateConfigurationItem
	{
		#region Initialization

		/// <summary>
		/// Initializes a new instance of the <see cref="UpdateConfigurationItem"/> class.
		/// </summary>
		/// <param name="isGroupHeader">if set to <c>true</c> [is group header].</param>
		/// <param name="showCheckBox">if set to <c>true</c> [show check box].</param>
		/// <param name="doUpdate">if set to <c>true</c> [do update].</param>
		/// <param name="elementText">The element text.</param>
		public UpdateConfigurationItem(bool isGroupHeader, bool showCheckBox, bool doUpdate,
			string elementText)
			: this(isGroupHeader, showCheckBox, doUpdate, elementText, "", "", "", 0, null)
		{
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="UpdateConfigurationItem"/> class.
		/// </summary>
		/// <param name="isGroupHeader">if set to <c>true</c> [is group header].</param>
		/// <param name="showCheckBox">if set to <c>true</c> [show check box].</param>
		/// <param name="doUpdate">if set to <c>true</c> [do update].</param>
		/// <param name="elementText">The element text.</param>
		/// <param name="comment">The comment.</param>
		public UpdateConfigurationItem(bool isGroupHeader, bool showCheckBox, bool doUpdate,
			string elementText, string comment, int indent, Image image)
			: this(isGroupHeader, showCheckBox, doUpdate, elementText, "", "", "", indent, image)
		{
			this.Comment = comment;
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="UpdateConfigurationItem"/> class.
		/// </summary>
		/// <param name="isGroupHeader">if set to <c>true</c> [is group header].</param>
		/// <param name="showCheckBox">if set to <c>true</c> [show check box].</param>
		/// <param name="doUpdate">if set to <c>true</c> [do update].</param>
		/// <param name="elementText">The element text.</param>
		/// <param name="propertyText">The property text.</param>
		/// <param name="newValueText">The new value text.</param>
		/// <param name="oldValueText">The old value text.</param>
		/// <param name="indent">The indent.</param>
		/// <param name="image">The image.</param>
		public UpdateConfigurationItem(bool isGroupHeader, bool showCheckBox, bool doUpdate,
			string elementText, string propertyText, string newValueText, string oldValueText,
			int indent, Image image)
		{
			this.IsGroupHeader = isGroupHeader;
			this.ShowCheckBox = showCheckBox;
			this._doUpdate = doUpdate;
			this.ElementText = elementText;
			if ( !string.IsNullOrEmpty(oldValueText) && !string.IsNullOrEmpty(newValueText) ) {
				this.Comment = string.Format("Old Value = {0} ; New Value = {1}", oldValueText, newValueText);
			} else if ( !string.IsNullOrEmpty(oldValueText) ) {
				this.Comment = string.Format("Old Value = {0}", oldValueText);
			} else if ( !string.IsNullOrEmpty(newValueText) ) {
				this.Comment = string.Format("New Value = {0}", newValueText);
			}
			this.Image = image;
			this.Indent = indent;
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="UpdateConfigurationItem"/> class.
		/// </summary>
		/// <param name="item">The item.</param>
		public UpdateConfigurationItem(IRepositoryItem item)
			: this(item, "")
		{
		}
		/// <summary>
		/// Initializes a new instance of the <see cref="UpdateConfigurationItem"/> class.
		/// </summary>
		/// <param name="item">The item.</param>
		/// <param name="oldValue">The old value.</param>
		public UpdateConfigurationItem(IRepositoryItem item, string oldValue)
			: this(false, true, true, "", "", "", "", 0, null)
		{
			if ( item == null ) throw new ArgumentNullException("item");

			string comment = null;
			string newValue = null;
			string propName = "Value";

			this.Item = item;
			this.ElementText = item.Display;
			this.Image = item.Image;

			RuleConstant rc = item as RuleConstant;
			RepositoryBusinessRule brule = item as RepositoryBusinessRule;
			WebService ws = item as WebService;
			Repository.HumanActivity ha = item as Repository.HumanActivity;
			BusinessObject bo = item as BusinessObject;
			LogicalWebMethod lm = item as LogicalWebMethod;
			if ( rc != null ) {
				newValue = rc.Value;
				if ( string.IsNullOrEmpty(oldValue) ) {
					oldValue = "n/a";
				}
				if ( oldValue == newValue ) {
					oldValue = newValue = "";
				}
			} else if ( brule != null ) {
				if ( oldValue.Contains("Changed") ) {
					comment = "Rule Changed";
				}
			} else if ( ws != null ) {
				propName = "URL";
				newValue = ws.Uri;
			} else if ( ha != null ) {
				propName = "URL";
				newValue = ha.Url.ToString();
			} else if ( bo != null ) {
				string oldValueText = oldValue;
				if ( oldValueText == string.Format("{0}Type", bo.Name) ) oldValueText = bo.Name;
				if ( oldValueText == "Changed" /*|| oldValue == bo.Name*/ ) {
					comment = "Structure Changed";
				} else if ( oldValueText != bo.Name && !string.IsNullOrEmpty(oldValueText) ) {
					comment = "Name Changed";
				} else {
					oldValue = "";
				}
			} else if ( lm != null ) {
				if ( !string.IsNullOrEmpty(oldValue) ) {
					if ( lm.IsAssignedTo == LogicalMethodAssignedTo.HumanActivity ) {
						newValue = lm.HumanActivity.Name;
					} else if ( lm.IsAssignedTo == LogicalMethodAssignedTo.WebServiceMethod ) {
						Repository.WebMethod wmProxy = lm.GetAssignedProxyWebMethod();
						if ( wmProxy != null ) {
							newValue = wmProxy.Name;
						} else {
							newValue = lm.WebMethod.Name;
						}
					} else if ( lm.IsAssignedTo == LogicalMethodAssignedTo.EndpointRule && lm.EndpointRule != null ) {
						newValue = "";
						foreach ( var ep in lm.GetLogicalRuleResultEndpoints() ) {
							if ( newValue != "" ) newValue += ", ";
							if ( ep.ProxyWebMethod != null ) {
								newValue += ep.ProxyWebMethod.Name;
							} else {
								newValue += ep.WebMethod.Name;
							}
						}
					}
					if ( oldValue == newValue ) oldValue = newValue = null;
				}
			}
			if ( item is Repository.Workflow ) {
				this._doUpdate = false;
			} else {
				this._doUpdate = ( !string.IsNullOrEmpty(oldValue) && newValue != oldValue );
			}
			if ( !string.IsNullOrEmpty(comment) ) {
				this.Comment = comment;
			} else if ( !string.IsNullOrEmpty(oldValue) && !string.IsNullOrEmpty(newValue) ) {
				this.Comment = string.Format("Old {2} = {0} ; New {2} = {1}", oldValue, newValue, propName);
			} else if ( !string.IsNullOrEmpty(oldValue) ) {
				this.Comment = string.Format("Old {1} = {0}", oldValue, propName);
			} else if ( !string.IsNullOrEmpty(newValue) ) {
				this.Comment = string.Format("New {1} = {0}", newValue, propName);
			}
		}
		/// <summary>
		/// Initializes a new instance of the <see cref="UpdateConfigurationItem"/> class.
		/// </summary>
		/// <param name="item">The item.</param>
		/// <param name="oldValue">The old value.</param>
		public UpdateConfigurationItem(MappingItem item, string oldValue)
			: this(false, true, true, "", "", "", "", 0, null)
		{
			if ( item == null ) throw new ArgumentNullException("item");

			this.Item = item;
			this.ElementText = item.Element;

			Bitmap bmp = Resources.bmp_mapping;
			bmp.MakeTransparent(Color.Magenta);
			this.Image = bmp;

			string newValue = ( item.Xslt == null ? "<Undefined>" : item.Xslt.InnerXml );
			this.Comment = ( !string.IsNullOrEmpty(oldValue) && oldValue != newValue ?
								item.Property + " Changed" : "" );
			this._doUpdate = ( !string.IsNullOrEmpty(oldValue) && newValue != oldValue );
		}
		#endregion

		#region Public Members

		#region Properties
		// displayed values
		private bool _doUpdate;
		public bool DoUpdate
		{
			get { return _doUpdate; }
			set
			{
				if ( this.Item is Repository.Workflow ) {
					_doUpdate = value;
				}
			}
		}
		public string ElementText { get; set; }
		public string Comment { get; set; }
		// control values
		public bool ShowCheckBox { get; set; }
		public bool IsGroupHeader { get; set; }
		// No Auto Prop, because only valid for headers!
		public bool IsCollapsed
		{
			get { return _collapsed; }
			set { if ( IsGroupHeader ) _collapsed = value; }
		}
		public int Indent { get; set; }
		public Image Image { get; set; }
		public object Item { get; set; }
		#endregion

		#region Methods
		public void SetDoUpdate(bool doUpdate)
		{
			_doUpdate = doUpdate;
		}
		#endregion

		#endregion

		#region Private Members
		private bool _collapsed = false;
		#endregion
	}
	#endregion

	#region Internal Static Class: UsingItems
	internal static class UsingItems
	{
		internal static void GetItemsOfNoun(Noun item)
		{
		}

		internal static void GetItemsOfBusinessObject(BusinessObject item,
			ref BindingListEx<Noun> nouns,
			ref BindingListEx<BusinessObject> bobjects)
		{
			foreach ( BusinessObjectField bof in item.BusinessObjectFields ) {
				if ( bof.NounID > 0 ) {
					nouns.AddDistinct(bof.Noun);
				} else if ( bof.BusinessObjectID > 0 ) {
					bobjects.AddDistinct(bof.BusinessObject);
				}
			}
		}

		internal static void GetItemsOfVerb(Verb item,
			ref BindingListEx<BusinessObject> bobjects,
			ref BindingListEx<LogicalWebMethod> lwms,
			ref BindingListEx<Noun> nouns,
			ref BindingListEx<RuleConstant> constants,
			ref BindingListEx<RepositoryBusinessRule> brules,
			ref BindingListEx<WebService> webservices,
			ref BindingListEx<Repository.HumanActivity> humanActs,
			ref BindingListEx<MappingItem> logphysmappings)
		{
			if ( item.InputBusinessObject != null ) {
				bobjects.AddDistinct(item.InputBusinessObject);
			}
			if ( item.OutputBusinessObject != null ) {
				bobjects.AddDistinct(item.OutputBusinessObject);
			}

			lwms.AddRangeDistinct(Global.Data.GetLogicalMethodsOfVerb(item.ID));

			BindingListEx<BusinessObject> newbobjs = new BindingListEx<BusinessObject>();
			foreach ( BusinessObject bo in bobjects ) {
				GetItemsOfBusinessObject(bo, ref nouns, ref newbobjs);
			}
			if ( newbobjs.Count > 0 ) bobjects.AddRangeDistinct(newbobjs);

			foreach ( LogicalWebMethod lwm in lwms ) {
				GetItemsOfLogicalMethod(lwm, ref bobjects, ref nouns, ref constants, ref brules,
					ref webservices, ref humanActs, ref logphysmappings);
			}
		}

		internal static void GetItemsOfBusinessRule(RepositoryBusinessRule item,
			ref BindingListEx<Noun> nouns,
			ref BindingListEx<RepositoryBusinessRule> brules,
			ref BindingListEx<RuleConstant> constants)
		{
			foreach ( var condition in item.ExtendedProperties.Conditions ) {
				if ( condition.LeftNounID > 0 ) {
					nouns.AddDistinct(Global.Data.RepositoryService.GetItem<Noun>(condition.LeftNounID));
				} else if ( condition.LeftRuleConstID > 0 ) {
					constants.AddDistinct(Global.Data.RepositoryService.GetItem<RuleConstant>(condition.LeftRuleConstID));
				} else if ( condition.LeftRuleID > 0 ) {
					brules.AddDistinct(Global.Data.RepositoryService.GetItem<RepositoryBusinessRule>(condition.LeftRuleID));
				}
				if ( condition.RightNounID > 0 ) {
					nouns.AddDistinct(Global.Data.RepositoryService.GetItem<Noun>(condition.RightNounID));
				} else if ( condition.RightRuleConstID > 0 ) {
					constants.AddDistinct(Global.Data.RepositoryService.GetItem<RuleConstant>(condition.RightRuleConstID));
				} else if ( condition.RightRuleID > 0 ) {
					brules.AddDistinct(Global.Data.RepositoryService.GetItem<RepositoryBusinessRule>(condition.RightRuleID));
				}
			}
		}

		internal static void GetItemsOfLogicalMethod(LogicalWebMethod item,
			ref BindingListEx<BusinessObject> bobjects,
			ref BindingListEx<Noun> nouns,
			ref BindingListEx<RuleConstant> constants,
			ref BindingListEx<RepositoryBusinessRule> brules,
			ref BindingListEx<WebService> webservices,
			ref BindingListEx<Repository.HumanActivity> humanActs,
			ref BindingListEx<MappingItem> logphysmappings)
		{
			if ( item.InputBusinessObjectID > 0 ) {
				bobjects.AddDistinct(item.InputBusinessObject);
				GetItemsOfBusinessObject(item.InputBusinessObject, ref nouns, ref bobjects);
				if ( item.ProxyInputXSLT != null ) {
					logphysmappings.AddDistinct(new MappingItem(item.Name + " Proxy Input Mapping", "", item.ProxyInputXSLT));
				} else if ( item.InputXSLT != null ) {
					logphysmappings.AddDistinct(new MappingItem(item.Name + " Input Mapping", "", item.InputXSLT));
				}
			}
			if ( item.OutputBusinessObjectID > 0 ) {
				bobjects.AddDistinct(item.OutputBusinessObject);
				GetItemsOfBusinessObject(item.OutputBusinessObject, ref nouns, ref bobjects);
				if ( item.ProxyOutputXSLT != null ) {
					logphysmappings.AddDistinct(new MappingItem(item.Name + " Proxy Output Mapping", "", item.ProxyOutputXSLT));
				} else if ( item.OutputXSLT != null ) {
					logphysmappings.AddDistinct(new MappingItem(item.Name + " Output Mapping", "", item.OutputXSLT));
				}
			}
			Repository.HumanActivity ha = item.GetAssignedHumanActivity();
			if ( ha != null ) humanActs.AddDistinct(ha);

			WebService ws = item.GetAssignedProxyWebService();
			if ( ws != null ) webservices.AddDistinct(ws);
			ws = item.GetAssignedWebService();
			if ( ws != null ) webservices.AddDistinct(ws);

			if ( item.WebServiceID > 0 ) {
				GetItemsOfWebService(item.WebService);
			}
			if ( item.EndpointRuleID > 0 ) {
				foreach ( LogicalRuleResultEndpoint ruleep in item.GetLogicalRuleResultEndpoints() ) {
					ha = ruleep.HumanActivity;
					if ( ha != null ) humanActs.AddDistinct(ha);
					ws = ruleep.ProxyWebService;
					if ( ws != null ) webservices.AddDistinct(ws);
					ws = ruleep.WebService;
					if ( ws != null ) webservices.AddDistinct(ws);
					if ( ruleep.ProxyInputXSLT != null ) {
						logphysmappings.AddDistinct(
							new MappingItem(item.Name + "_" + ruleep.EndpointRuleResult + " Proxy Input Mapping", "", ruleep.ProxyInputXSLT));
					} else if ( ruleep.InputXSLT != null ) {
						logphysmappings.AddDistinct(
							new MappingItem(item.Name + "_" + ruleep.EndpointRuleResult + " Input Mapping", "", ruleep.InputXSLT));
					}
					if ( ruleep.ProxyOutputXSLT != null ) {
						logphysmappings.AddDistinct(
							new MappingItem(item.Name + "_" + ruleep.EndpointRuleResult + " Proxy Output Mapping", "", ruleep.ProxyOutputXSLT));
					} else if ( ruleep.OutputXSLT != null ) {
						logphysmappings.AddDistinct(
							new MappingItem(item.Name + "_" + ruleep.EndpointRuleResult + " Output Mapping", "", ruleep.OutputXSLT));
					}
				}
				GetItemsOfBusinessRule(item.EndpointRule, ref nouns, ref brules, ref constants);
			}
		}

		internal static void GetItemsOfWebMethod(WebMethod item,
			ref BindingListEx<LogicalWebMethod> lwms,
			ref BindingListEx<BusinessObject> bobjects,
			ref BindingListEx<Noun> nouns,
			ref BindingListEx<RuleConstant> constants,
			ref BindingListEx<RepositoryBusinessRule> brules,
			ref BindingListEx<WebService> webservices,
			ref BindingListEx<Repository.HumanActivity> humanActs,
			ref BindingListEx<MappingItem> logphysmappings)
		{
			lwms.AddRangeDistinct(Global.Data.GetLogicalWebMethodsOfWebMethod(item.ID));
			foreach ( LogicalWebMethod method in lwms ) {
				GetItemsOfLogicalMethod(method, ref bobjects, ref nouns, ref constants, ref brules,
					ref webservices, ref humanActs, ref logphysmappings);
			}
		}

		internal static void GetItemsOfWebService(WebService item)
		{
		}

		internal static void GetItemsOfHumanActivity(Repository.HumanActivity item,
			ref BindingListEx<LogicalWebMethod> lwms)
		{
			lwms.AddRangeDistinct(Global.Data.GetLogicalWebMethodsOfHumanActivity(item.ID));
		}

		internal static void GetItemsOfRuleConstants(RuleConstant item,
			ref BindingListEx<RepositoryBusinessRule> rules)
		{
			rules.AddRangeDistinct(Global.Data.GetBusinessRulesOfRuleConstant(item.ID));
		}

		internal static void GetItemsOfCapability(ServiceModule item,
			ref BindingListEx<Verb> verbs,
			ref BindingListEx<Repository.Workflow> workflows,
			ref BindingListEx<BusinessObject> bobjects,
			ref BindingListEx<LogicalWebMethod> lwms,
			ref BindingListEx<Noun> nouns,
			ref BindingListEx<RuleConstant> constants,
			ref BindingListEx<RepositoryBusinessRule> brules,
			ref BindingListEx<WebService> webservices,
			ref BindingListEx<Repository.HumanActivity> humanActs,
			ref BindingListEx<MappingItem> logphysmappings)
		{
			verbs.AddRangeDistinct(item.GetVerbs());

			foreach ( Verb verb in verbs ) {
				GetItemsOfVerb(verb, ref bobjects, ref lwms, ref nouns, ref constants, ref brules,
					ref webservices, ref humanActs, ref logphysmappings);
			}
			workflows = new BindingListEx<Repository.Workflow>();
			foreach ( Verb verb in verbs ) {
				workflows.AddRangeDistinct(Global.Data.GetWorkflowsOfVerb(verb.ID));
			}

		}

		internal static void GetItemsOfWorkflow(Repository.Workflow item,
			ref BindingListEx<Verb> verbs,
			ref BindingListEx<LogicalActivity> logActs,
			ref BindingListEx<RepositoryBusinessRule> rules,
			ref BindingListEx<Repository.HumanActivity> humanActs,
			ref BindingListEx<WebService> webservices,
			ref BindingListEx<WorkflowEvent> events,
			ref BindingListEx<WorkflowMethod> methods,
			ref BindingListEx<WorkflowField> fields,
			ref BindingListEx<BusinessObject> bobjects,
			ref BindingListEx<LogicalWebMethod> lwms,
			ref BindingListEx<Noun> nouns,
			ref BindingListEx<RuleConstant> constants,
			ref BindingListEx<MappingItem> logphysmappings,
			ref BindingListEx<MappingItem> submappings)
		{
			verbs = new BindingListEx<Verb>();
			if ( item.Capability != null ) {
				verbs.AddDistinct(item.Capability);
			}
			logActs.AddRangeDistinct(Global.Data.GetLogicalActivitiesOfWorkflow(item.ID));
			rules.AddRangeDistinct(item.GetRules());
			foreach ( LogicalActivity logAct in logActs ) {
				Verb v = logAct.Verb;
				if ( v != null ) verbs.AddDistinct(v);
				RepositoryBusinessRule r = logAct.GetBusinessRule();
				if ( r != null ) rules.AddDistinct(r);
				Repository.HumanActivity ha = logAct.GetHumanActivity();
				if ( ha != null ) humanActs.AddDistinct(ha);
				WebService ws = logAct.GetWebService();
				if ( ws != null ) webservices.AddDistinct(ws);
			}
			foreach ( Verb verb in verbs ) {
				GetItemsOfVerb(verb, ref bobjects, ref lwms, ref nouns, ref constants, ref rules,
					ref webservices, ref humanActs, ref logphysmappings);
			}
			foreach ( WebService ws in webservices ) {
				GetItemsOfWebService(ws);
			}
			events.AddRangeDistinct(Global.Data.GetWorkflowEvents(item.ID));
			foreach ( var e in events ) {
				if ( e.BusinessObjectID > 0 ) bobjects.AddDistinct(e.BusinessObject);
			}
			methods.AddRangeDistinct(Global.Data.GetWorkflowMethods(item.ID));
			foreach ( var m in methods ) {
				if ( m.InputBusinessObjectID > 0 ) bobjects.AddDistinct(m.InputBusinessObject);
				if ( m.OutputBusinessObjectID > 0 ) bobjects.AddDistinct(m.OutputBusinessObject);
			}
			fields.AddRangeDistinct(Global.Data.GetWorkflowFields(item.ID));
			foreach ( var f in fields ) {
				if ( f.BusinessObjectID > 0 ) bobjects.AddDistinct(f.BusinessObject);
			}
			// get rule items
			int counter = 0;
			while ( rules.Count > counter ) {
				UsingItems.GetItemsOfBusinessRule(rules[counter], ref nouns, ref rules, ref constants);
				counter++;
			}
			// get Logical Method Items
			foreach ( LogicalWebMethod lwm in lwms ) {
				UsingItems.GetItemsOfLogicalMethod(lwm, ref bobjects, ref nouns, ref constants, ref rules,
					ref webservices, ref humanActs, ref logphysmappings);
			}
			// get business object items
			counter = 0;
			while ( bobjects.Count > counter ) {
				UsingItems.GetItemsOfBusinessObject(bobjects[counter], ref nouns, ref bobjects);
				counter++;
			}
			// get subscription mappings
			foreach ( var logact in logActs ) {
				if ( logact.InputXslt != null ) {
					LogicalWebMethod lm = logact.LogicalMethod;
					if ( lm == null || lm.EndpointRule == null ) {
						submappings.AddDistinct(new MappingItem(
							lm == null ? logact.Name : lm.Name,
							"Mapping", logact.InputXslt));
					} else {
						BindingListEx<LogicalRuleResultEndpoint> endpoints = lm.GetLogicalRuleResultEndpoints();
						foreach ( LogicalRuleResultEndpoint endpoint in endpoints ) {
							submappings.AddDistinct(new MappingItem(
								string.Format("{0}_{1}", lm.Name, endpoint.EndpointRuleResult),
								"Mapping", logact.InputXslt));
						}
					}
				}
			}
		}
	}
	#endregion

	#region Internal Class: WFConfig
	internal class WFConfig
	{
		public WFConfig()
		{
			this.XmlConfigs = new List<Configuration>();
			this.AssemblyConfigPaths = new List<string>();
			this.RepositoryItems = new List<IRepositoryItem>();
			this.MappingItems = new List<MappingItem>();
			this.UpdateItem = null;
		}
		public List<Configuration> XmlConfigs;
		public List<string> AssemblyConfigPaths;
		public List<IRepositoryItem> RepositoryItems;
		public List<MappingItem> MappingItems;
		public UpdateConfigurationItem UpdateItem;
	}
	#endregion

	#region Internal Class: MappingItem
	internal class MappingItem
	{
		public MappingItem(string element, string property, XsltDocument xslt)
		{
			this.Element = element;
			this.Property = property;
			this.Xslt = xslt;
		}
		public string Element { get; set; }
		public string Property { get; set; }
		public XsltDocument Xslt { get; set; }

		public override bool Equals(object obj)
		{
			MappingItem mi = obj as MappingItem;
			if ( mi == null ) return false;

			return ( this.Element == mi.Element && this.Property == mi.Property );
		}
		public override int GetHashCode()
		{
			return ( this.Element.GetHashCode() ^ this.Property.GetHashCode() );
		}
	}
	#endregion
}
